package net.siufung.web.aop.aspect;

import cn.hutool.crypto.digest.MD5;
import com.google.common.base.Strings;
import lombok.AllArgsConstructor;
import net.siufung.core.exception.BizServiceException;
import net.siufung.security.api.AuthUtil;
import net.siufung.web.aop.annotation.AutoIdempotent;
import net.siufung.web.aop.service.IAutoIdempotentService;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;

import java.lang.reflect.Method;
import java.util.Objects;

/**
 * @author 陈建峰
 * @date 2022/10/4 12:01 上午
 * @since V1.0.0
 */
@Aspect
@AllArgsConstructor
public class AutoIdempotentAspect {

    private final IAutoIdempotentService autoIdempotentService;

    @Pointcut("@annotation(net.siufung.web.aop.annotation.AutoIdempotent)")
    public void autoIdempotentPointCut() {}

    @Around("autoIdempotentPointCut()")
    public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        Object proceed = proceedingJoinPoint.proceed();
        MethodSignature signature = (MethodSignature) proceedingJoinPoint.getSignature();
        Method method = signature.getMethod();
        AutoIdempotent autoIdempotent = method.getAnnotation(AutoIdempotent.class);
        if(Objects.nonNull(autoIdempotent)){
            String userUniqueKey = AuthUtil.getUserId();
            if(Strings.isNullOrEmpty(userUniqueKey)){
                return  proceed;
            }
            if(Strings.isNullOrEmpty(autoIdempotent.key())){
                throw new BizServiceException("幂等KEY不能为空！");
            }
            String autoIdempotentKey = autoIdempotent.key() + userUniqueKey;
            if (Objects.nonNull(autoIdempotentService.getCache(autoIdempotentKey))){
                throw new BizServiceException(autoIdempotent.description());
            } else {
                autoIdempotentService.putCache(autoIdempotentKey,
                        MD5.create().digestHex16(userUniqueKey), autoIdempotent.timeout(), autoIdempotent.timeoutUnit());
            }
        }
        return proceed;
    }

}
